﻿using System;
using System.Diagnostics;
using System.IO;
using System.Xml.Serialization;
using SterlingLib;

namespace Algobox.Interop.SterlingTrader
{
    public class QuoteManagement
    {
        private bool _isStarted = false;
        XmlSerializer _serialiserOnSTIQuoteSnapXML = new XmlSerializer(typeof(SterlingLib.structSTIQuoteSnap));
        XmlSerializer _serialiserSTIQuoteUpdateXML = new XmlSerializer(typeof(SterlingLib.structSTIQuoteUpdate));
        XmlSerializer _serialiserSTIBookUpdateXML = new XmlSerializer(typeof(SterlingLib.structSTIBookUpdate));
        
        public virtual bool Start()
        {
            if (!_isStarted)
            {                
                if (!SterlingWrapper.STIApp.IsApiEnabled())
                    return false;

                try
                {
                    if (SterlingWrapper.STIEvents == null)
                    {
                        SterlingWrapper.STIEvents = new SterlingLib.STIEvents();
                    }

                    SterlingWrapper.STIEvents.OnSTIShutdown += new _ISTIEventsEvents_OnSTIShutdownEventHandler(SterlingWrapper.OnSTIShutdown);
                }
                catch
                {
                    return false;
                }

                try
                {
                    if (SterlingWrapper.STIQuotes == null)
                    {
                        SterlingWrapper.STIQuotes = new SterlingLib.STIQuote();
                        SterlingWrapper.STIQuotes.OnSTIQuoteUpdateXML += new _ISTIQuoteEvents_OnSTIQuoteUpdateXMLEventHandler(OnSTIQuoteUpdateXML);
                        SterlingWrapper.STIQuotes.OnSTIQuoteSnapXML += new _ISTIQuoteEvents_OnSTIQuoteSnapXMLEventHandler(OnSTIQuoteSnapXML);
                    }

                    if (SterlingWrapper.STIBook == null)
                    {
                        SterlingWrapper.STIBook = new SterlingLib.STIBook();
                        SterlingWrapper.STIBook.OnSTIBookUpdateXML += new _ISTIBookEvents_OnSTIBookUpdateXMLEventHandler(OnSTIBookUpdateXML);
                    }

                    SterlingWrapper.OnSterlingShutdown += new SterlingWrapper.STIShutdown(OnSterlingShutdown);
                }
                catch
                {
                    return false;
                }
                _isStarted = true;
            }
            return true;
        }

        public virtual void Stop()
        {
            if (_isStarted)
            {
                if (SterlingWrapper.STIQuotes != null)
                {
                    try
                    {
                        SterlingWrapper.STIQuotes.DeRegisterAllQuotes();
                        SterlingWrapper.STIQuotes.Destroy();
                    }
                    catch
                    { }
                    SterlingWrapper.STIQuotes = null;
                }
                if (SterlingWrapper.STIBook != null)
                {
                    try
                    {
                        SterlingWrapper.STIBook.DeRegisterForAllTopOfBookMsgs();
                        SterlingWrapper.STIBook.Destroy();
                    }
                    catch
                    { }
                    SterlingWrapper.STIQuotes = null;
                }
                _isStarted = false;
            }
        }

        protected bool RegisterQuote(string symbol, string exchange)
        {
            try
            {
                if (_isStarted && SterlingWrapper.STIQuotes != null)
                    SterlingWrapper.STIQuotes.RegisterQuote(symbol, exchange);
            }
            catch
            {
                return false;
            }
            return true;
        }

        protected bool RegisterForTopOfBookMsgs(string symbol, string book)
        {
            try
            {
                if (_isStarted && SterlingWrapper.STIBook != null)
                    SterlingWrapper.STIBook.RegisterForTopOfBookMsgs(symbol, book);
            }
            catch
            {
                return false;
            }
            return true;
        }

        protected bool DeRegisterQuote(string symbol, string exchange)
        {
            try
            {
                if (_isStarted && SterlingWrapper.STIQuotes != null)
                    SterlingWrapper.STIQuotes.DeRegisterQuote(symbol, exchange);
            }
            catch
            { 
                return false; 
            }
            return true;
        }

        protected bool DeRegisterForTopOfBookMsgs(string symbol, string book)
        {
            try
            {
                if (_isStarted && SterlingWrapper.STIBook != null)
                    SterlingWrapper.STIBook.DeRegisterForTopOfBookMsgs(symbol, book);
            }
            catch
            {
                return false;
            }
            return true;
        }

        void OnSTIQuoteSnapXML(ref string quoteSnapXML)
        {
            structSTIQuoteSnap stiQuoteSnap = (structSTIQuoteSnap)_serialiserOnSTIQuoteSnapXML.Deserialize(new StringReader(quoteSnapXML));
            PostProcessQuoteSnapshot(ref stiQuoteSnap);
        }

        void OnSTIQuoteUpdateXML(ref string quoteUpdateXML)
        {
            structSTIQuoteUpdate stiQuoteUpdate = (structSTIQuoteUpdate)_serialiserSTIQuoteUpdateXML.Deserialize(new StringReader(quoteUpdateXML));
            PostProcessQuoteUpdate(ref stiQuoteUpdate);
        }

        void OnSTIBookUpdateXML(ref string bookUpdateXML)
        {
            structSTIBookUpdate stiBookUpdate = (structSTIBookUpdate)_serialiserSTIBookUpdateXML.Deserialize(new StringReader(bookUpdateXML));
            PostProcessBookUpdate(ref stiBookUpdate);
        }        

        void OnSterlingShutdown()
        {
            _isStarted = false;
            PostProcessSterlingShutdown();
        }

        public virtual void PostProcessQuoteSnapshot(ref structSTIQuoteSnap stiQuoteSnap)
        {
            Debug.WriteLine(String.Format("SNAP {0} {1} {2}:{3}<->{4}:{5} {6} {7}", stiQuoteSnap.bstrSymbol, stiQuoteSnap.bstrBidExch, stiQuoteSnap.nBidSize, stiQuoteSnap.fBidPrice, stiQuoteSnap.fAskPrice, stiQuoteSnap.nAskSize, stiQuoteSnap.bstrAskExch, stiQuoteSnap.bstrUpdateTime));
        }

        public virtual void PostProcessQuoteUpdate(ref structSTIQuoteUpdate stiQuoteUpdate)
        {
            if (stiQuoteUpdate.bAskPrice == 1 && stiQuoteUpdate.bBidPrice == 1)
                Debug.WriteLine(String.Format("BBO  {0} {1} {2}:{3}<->{4}:{5} {6} {7} {8}", stiQuoteUpdate.bstrSymbol, stiQuoteUpdate.bstrBidExch, stiQuoteUpdate.nBidSize, stiQuoteUpdate.fBidPrice, stiQuoteUpdate.fAskPrice, stiQuoteUpdate.nAskSize, stiQuoteUpdate.bstrAskExch, stiQuoteUpdate.bstrHaltResumeStatus, stiQuoteUpdate.bstrUpdateTime));

            if (stiQuoteUpdate.bLastPrice == 1)
                Debug.WriteLine(String.Format("LAST {0} {1} {2}@{3} {4}", stiQuoteUpdate.bstrSymbol, stiQuoteUpdate.bstrLastExch, stiQuoteUpdate.nLastSize, stiQuoteUpdate.fLastPrice, stiQuoteUpdate.bstrUpdateTime));
        }

        public virtual void PostProcessBookUpdate(ref structSTIBookUpdate stiBookUpdate)
        {
            Debug.WriteLine(String.Format("LAST {0} {1} {2}@{3} {4} {5} {6}", stiBookUpdate.bstrSymbol, stiBookUpdate.bstrOrigin, stiBookUpdate.nQty, stiBookUpdate.fPrice, stiBookUpdate.bstrTime, stiBookUpdate.bstrSide, stiBookUpdate.bMsgSnapShot));
        }

        public virtual void PostProcessSterlingShutdown()
        {
            Debug.WriteLine("SHUTDOWN " + DateTime.Now);
        }
    }
}
